
package com.dkm.modules.sys.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dkm.commons.Response;
import com.dkm.constant.CacheConstant;
import com.dkm.constant.Constant;
import com.dkm.constant.UserErrorEnum;
import com.dkm.exception.ServiceException;
import com.dkm.modules.sys.operator.model.OperatorSelect;
import com.dkm.modules.sys.operator.model.UserDatascopePO;
import com.dkm.modules.sys.operator.service.OperatorService;
import com.dkm.modules.sys.role.mapper.UserRoleMapper;
import com.dkm.modules.sys.role.model.RolePO;
import com.dkm.modules.sys.role.service.RoleService;
import com.dkm.modules.sys.user.mapper.CustomerBalanceMapper;
import com.dkm.modules.sys.user.mapper.CustomerMapper;
import com.dkm.modules.sys.user.mapper.UserDatascopeMapper;
import com.dkm.modules.sys.user.mapper.UserMapper;
import com.dkm.modules.sys.user.model.*;
import com.dkm.modules.sys.user.service.CustomerBalanceService;
import com.dkm.modules.sys.user.service.UserService;
import com.dkm.modules.wx.card.mapper.CardMapper;
import com.dkm.modules.wx.card.mapper.RechargeRecodMapper;
import com.dkm.modules.wx.card.model.Card;
import com.dkm.modules.wx.card.model.RechargeRecodPO;
import com.dkm.modules.wx.card.service.CardService;
import com.dkm.modules.wx.login.model.LoginForm;
import com.dkm.util.StringUtils;
import com.dkm.util.auth.AuthUtils;
import com.dkm.util.http.HttpClientUtil;
import com.dkm.util.redis.RedisUtils;
import com.dkm.util.token.JwtTokenUtil;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName UserServiceImpl
 * @Description: 系统用户实现类
 * @Author yangbin
 * @Date 2019-09-18 00:01
 * @Version V1.0
 **/
@Service
public class UserServiceImpl implements UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    CustomerMapper customerMapper;

    @Autowired
    CustomerBalanceService customerBalanceService;

    @Autowired
    CustomerBalanceMapper customerBalanceMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    WxPayService wxPayService;

    @Autowired
    RechargeRecodMapper rechargeRecodMapper;

    @Autowired
    CardService cardService;

    @Autowired
    CardMapper cardMapper;

    /**
     * 微信商户号
     */
    @Value("${wx.pay.mchId}")
    private String mchId;

    @Value("${wx.refund.notify.url}")
    private String notifyUrl;
    /**
     * token 前缀
     */
    @Value("${remote.prefix}")
    private String remotePrefix;

    @Value("${wx.pay.appid}")
    String appId;

    @Value("${wx.pay.AppSecret}")
    String appSecret;

    @Autowired
    private RoleService roleService;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private UserDatascopeMapper userDatascopeMapper;
    @Autowired
    private OperatorService operatorService;

    /**
     * token 过期时间  单位秒   2小时
     */
    private static long AUTH_EXPIRE = 60 * 60 * 2;


    /**
     * 功能描述：代理商或者运营端登录
     *
     * @param form    用户登录
     * @param session session信息
     * @param type    登录类型，1代理商，0 运营端
     * @Return:com.dkm.commons.Response 返回结果
     * @Author: Guo Liangbo
     * @Date:2019/11/8 21:07
     */
    @Override
    public Response signIn(LoginForm form, HttpSession session, Integer type) {
        /*检验用户名密码是否为空*/
        String userName = form.getUserName();
        User user = userMapper.selectById(userName);
        // 如果按用户名查不到，使用电话号码查一下
        if (null == user) {
            user = userMapper.selectByTelephone(userName);
        }
        if (user != null) {
            userName = user.getUseraccount();
            String password1 = AuthUtils.md5Hex(form.getPassword(), user.getSalt());
            if (password1.equals(user.getPassword())) {
                // 判断是否代理商，不允许代理商登录
               /* if (Constant.LOGIN_TYPE_NOT_OPERATOR.equals(type) && !type.equals(user.getIsOperator())) {
                    return Response.error(UserErrorEnum.DAILI_CANNOT_LOGIN);
                }*/
                // 代理商状态为禁用，不允许登录
                if (type.equals(user.getIsOperator()) && StringUtils.equals("0", user.getState())) {
                    return Response.error(-1, "用户已禁用，不允许登录");
                }

                //登录成功,将Token最为键，用户信息作为值存入Redis
                String accessToken = JwtTokenUtil.generateToken(userName);
                Date expire = JwtTokenUtil.getClaimFromToken(accessToken).getExpiration();
                String key = remotePrefix + accessToken;
                //登录成功,将Token最为键，用户信息作为值存入Redis
                redisUtils.delete(key);
                redisUtils.set(key, userName, AUTH_EXPIRE);
                redisUtils.set(CacheConstant.User.PREFIX_NAME + userName, JSON.toJSONString(user), AUTH_EXPIRE);
                Map<String, Object> result = new HashMap<>();
                result.put("token", accessToken);
                result.put("userName", userName);
                /*类型转换*/
                String userStr = JSONObject.toJSONString(user);
                EditUser user1 = JSONObject.parseObject(userStr, EditUser.class);
                result.put("userInfo", user1);
                // 过期时间
                result.put("expire", expire);
                if (Constant.LOGIN_TYPE_NOT_OPERATOR.equals(type) && !type.equals(user.getIsOperator())) {
                    // TODO:获取用户的菜单

                }
                session.setAttribute(Constant.USERINFO_SESSION_KEY, getUserById(userName));
                return Response.ok(result);
            }

        }
        return Response.error(UserErrorEnum.SIGN_IN_INPUT_FAIL);
    }


    @Override
    /**
     *@描述 添加人员
     *@参数 [user 用户数据]
     *@返回值 void
     *@创建人 yangbin
     *@创建时间 2019/10/9
     */
    public int addUser(AddUser user) {

        if (!StringUtils.isPhoneNumber(user.getMobile())) {
            throw new IllegalArgumentException("手机号格式不正确");
        }
        User userByMobile = userMapper.getAgentByMobile(user.getMobile());
        if (userByMobile != null) {
            throw new IllegalArgumentException("手机号已存在，请换一个手机号");
        }
        User existingUser = userMapper.selectById(user.getUseraccount());
        if (existingUser != null) {
            throw new IllegalArgumentException("用户名" + user.getUseraccount() + "已存在");
        }

        /*类型转换*/
        String userStr = JSONObject.toJSONString(user);
        User user1 = JSONObject.parseObject(userStr, User.class);
        //加盐处理
        String salt = AuthUtils.getRandomString(AuthUtils.SALT_LENGTH);
        /*默认密码admin123456*/
        String password = AuthUtils.md5Hex(Constant.USER_DEFAULT_PASSWORD, salt);
        user1.setPassword(password);
        user1.setSalt(salt);
        user1.setCreatetime(new Date());
        /*插入用户表*/
        int id = userMapper.insert(user1);
        return id;
    }


    @Override
    /**
     *@描述 修改密码
     *@参数 [password, newPassword, userId]
     *@返回值 com.dkm.commons.Response
     *@创建人 yangbin
     *@创建时间 2019/10/13
     */
    public Response changePwd(String password, String newPassword, String userId) {
        // 查出用户信息
        User user = userMapper.selectById(userId);
        if (user != null) {
            // 判断原密码是否正确
            String password1 = AuthUtils.md5Hex(password, user.getSalt());
            if (!password1.equals(user.getPassword())) {
                return Response.error(UserErrorEnum.PASSWORD_ERROR);
            }
            /*设置新密码*/
            String newPass = AuthUtils.md5Hex(newPassword, user.getSalt());
            user.setPassword(newPass);
            userMapper.updateById(user);
            return Response.ok();
        }
        return Response.error(UserErrorEnum.USERID_IS_NULL);
    }


    @Override
    /**
     *@描述 获取用户信息
     *@参数 [userNm 用户名]
     *@返回值 com.dkm.modules.sys.user.model.User
     *@创建人 yangbin
     *@创建时间 2019/10/1
     */
    public User getUserById(String userNm) {
        String s = redisUtils.get(CacheConstant.User.PREFIX_NAME + userNm);
        if (StringUtils.isNotEmpty(s)) {
            return JSON.parseObject(s, User.class);
        }

        /*通过用户账号查询用户*/
        User user = userMapper.selectById(userNm);
        /*设置用户角色数据*/
        List<RolePO> roles = roleService.getRoleByUserId(user.getId());
        user.setRoles(roles);
        Integer[] scopeArr = getDataScopeArr(userNm);
        user.setDataScope(scopeArr);
        return user;
    }

    private Integer[] getDataScopeArr(String usrNm) {
        List<OperatorSelect> operatorSelects = getUserScope(usrNm);
        if (operatorSelects == null) {
            return null;
        }
        Integer[] dataScope = new Integer[operatorSelects.size()];
        int i = 0;
        for (OperatorSelect o : operatorSelects) {
            dataScope[i] = o.getOperatorId();
        }
        return dataScope;
    }

    @Override
    /**
     *@描述 获取用户数据权限
     *@参数 [userId 当前登录用户的id]
     *@返回值 java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     *@创建人 yangbin
     *@创建时间 2019/10/4
     */
    public List<OperatorSelect> getUserScope(String userNm) {
        User user = userMapper.selectById(userNm);
        /*通过角色获取用户可看代理商list*/
        List<OperatorSelect> scopeList = operatorService.getOperatorSelect();
        /*如果数据权限为全部 显示所有代理商*/
        Integer DataPermissions = user.getDataPermissions();
        if (DataPermissions == 2) {
            return null;
        } else if (DataPermissions == 3) {
            QueryWrapper<UserDatascopePO> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id", user.getId());
            List<UserDatascopePO> userDatascopes = userDatascopeMapper.selectList(queryWrapper);
            if (CollectionUtils.isNotEmpty(userDatascopes)) {
                List<Integer> opId = userDatascopes.stream().map(UserDatascopePO::getOperatorId).collect(Collectors.toList());
                return scopeList.stream().filter(os -> opId.contains(os.getOperatorId())).collect(Collectors.toList());
            }
            return null;
        }
        return scopeList;
    }

    @Override
    /**
     *@描述 删除用户
     *@参数 [id 用户ID]
     *@返回值 void
     *@创建人 yangbin
     *@创建时间 2019/10/19
     */
    public void delUser(Integer id) {
        if (Objects.isNull(id)) {
            throw new ServiceException("用户id必填");
        }
        User user = new User();
        user.setState("2");
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);

        userMapper.update(user, updateWrapper);
    }

    @Override
    /**
     *@描述 修改用户
     *@参数 [user]
     *@返回值 void
     *@创建人 yangbin
     *@创建时间 2019/10/12
     */
    public void updateUser(EditUser user) {
        String mobile = user.getMobile();
        if (StringUtils.isBlank(mobile)) {
            user.setMobile(null);
        }

        if (StringUtils.isNotBlank(mobile)) {
            Map<String, Object> param = new HashMap();
            param.put("mobile", mobile);
            List<User> users = userMapper.selectByMap(param);
            if (CollectionUtils.isNotEmpty(users)) {
                if (users.size() > 1) {
                    throw new ServiceException("手机号已被占用,请换一个");
                }
                User user1 = users.get(0);
                if (!user1.getUseraccount().equals(user.getUseraccount())) {
                    throw new ServiceException("手机号已被占用,请换一个");
                }
            }
        }

        user.setId(null);
        /*类型转换*/
        String userStr = JSONObject.toJSONString(user);
        User user1 = JSONObject.parseObject(userStr, User.class);
        userMapper.updateById(user1);
    }

    @Override
    /**
     *@描述 用户列表
     *@参数 [params, page]
     *@返回值 com.baomidou.mybatisplus.core.metadata.IPage<com.dkm.modules.sys.user.model.UserResult>
     *@创建人 yangbin
     *@创建时间 2019/10/20
     */
    public IPage<UserResult> getUserList(Map<String, Object> params, Page<UserResult> page) {
        List<UserResult> results = userMapper.getUserList(params, page);
        // 补充数据权限
        setUserDataScoprArr(results);

        page.setRecords(results);
        return page;
    }

    private void setUserDataScoprArr(List<UserResult> results) {
        if (CollectionUtils.isEmpty(results)) {
            return;
        }
        // 获取所有代理商
        List<OperatorSelect> allOperator = operatorService.getOperatorSelect();

        for (UserResult result : results) {
            if (result.getDataPermissions().equals(Constant.DATA_PERMISSIONS_ALL)) {
                result.setDataScopeArr("全部");
            } else if (result.getDataPermissions().equals(Constant.DATA_PERMISSIONS_SELF)) {
                result.setDataScopeArr("自己");
            } else if (result.getDataPermissions().equals(Constant.DATA_PERMISSIONS_CUSTOM)) {
                // 获取所有自定义数据权限的用户id
                List<Integer> customUId = results.stream()
                        .filter(user -> user.getDataPermissions().equals(Constant.DATA_PERMISSIONS_CUSTOM))
                        .map(UserResult::getId)
                        .collect(Collectors.toList());
                // 查询自定义权限
                List<UserDatascopePO> userDatascopePOS = userDatascopeMapper.selectList(new QueryWrapper<UserDatascopePO>().in("user_id", customUId));
                Map<Integer, List<UserDatascopePO>> userIdMap = userDatascopePOS.stream()
                        .collect(Collectors.groupingBy(UserDatascopePO::getUserId));
                List<UserDatascopePO> pos = userIdMap.get(result.getId());
                if(CollectionUtils.isEmpty(pos)){
                    result.setDataScopeArr("");
                }else {
                    List<Integer> operIds = pos.stream().map(UserDatascopePO::getOperatorId).collect(Collectors.toList());
                    String dataArr =allOperator.stream()
                            .filter(os -> operIds.contains(os.getOperatorId()))
                            .map(OperatorSelect::getOperatorNm)
                            .collect(Collectors.joining(","));
                    result.setDataScopeArr(dataArr);
                }
            }
        }
    }


    /**
     * @描述 配置角色
     * @参数 [id 用户ID roleResults 角色list 数据]
     * @返回值 void
     * @创建人 yangbin
     * @创建时间 2019/10/20
     */
    @Override
    @Transactional
    public void setUserRole(UserRoles roleResults) {
        if (roleResults == null) {
            return;
        }
        roleService.updateUserRole(roleResults);
    }

    /**
     * @描述 绑定微信
     * @参数 [userId 用户ID, openId 微信openID]
     * @返回值 void
     * @创建人 yangbin
     * @创建时间 2019/10/25
     */
    @Override
    public Response bindWx(String userId, String code) {
        //获取access_token
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                "?appid=" + appId +
                "&secret=" + appSecret +
                "&code=" + code +
                "&grant_type=authorization_code";
        String result = HttpClientUtil.doGet(url);

        //返回结果的json对象
        JSONObject resultObject = JSON.parseObject(result);
        if (resultObject.containsKey(Constant.WECHAT_ERR_CODE)) {
            logger.error("微信登录异常，异常信息：" + resultObject.toString());
            return Response.error(-5, "获取openId异常！");
        }
        String openId = resultObject.getString("openid");
        User user = userMapper.selectById(userId);
        user.setWeixinOpenid(openId);
        Integer num = userMapper.updateById(user);
        if (num > 0) {
            return Response.ok();
        } else {
            return Response.error(-1, "bindWx error!");
        }
    }

    @Override
    /**
     *@描述 分配代理商
     *@参数 [operatorSet]
     *@返回值 void
     *@创建人 yangbin
     *@创建时间 2019/10/31
     */
    public void setOperator(OperatorSet operatorSet) {
        Integer[] scopes = operatorSet.getOperatorsId();
        UserDatascopePO userDatascope = new UserDatascopePO();
        userDatascope.setUserId(operatorSet.getUserId());
        for (int i = 0; i < scopes.length; i++) {
            userDatascope.setOperatorId(scopes[i]);
            userDatascopeMapper.insert(userDatascope);
        }
    }

    @Override
    /** 根据用户更新
     *@描述
     *@参数 [useId  用户ID]
     *@返回值 void
     *@创建人 yangbin
     *@创建时间 2019/11/10
     */
    public void updateUserByNm(EditUser user) {
        /*类型转换*/
        String userStr = JSONObject.toJSONString(user);
        User user1 = JSONObject.parseObject(userStr, User.class);
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq("id", user.getId());
        userMapper.update(user1, queryWrapper);
    }

    @Override
    /**
     *@描述 获取代理商select
     *@参数 []
     *@返回值 java.util.List<com.dkm.modules.sys.role.model.ScopeResult>
     *@创建人 yangbin
     *@创建时间 2019/11/10
     */
    public List getOperatorSelect() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_operator", 1);
        List<User> users = userMapper.selectList(queryWrapper);
//        List<ScopeResult> operatorSelects = new ArrayList<>();
//        for (User user : users) {
//            ScopeResult o = new ScopeResult();
//            o.setOperatorNm(user.getRealName());
//            o.setOperatorId(user.getId());
//            operatorSelects.add(o);
//        }
        return null;
    }

    @Override
    public Response resetPassword(Integer userId, Integer operatorId) {
        // 校验用户是否运营者，只有运营人员可以进行重置密码
        User xtOperator = userMapper.selectByUserId(operatorId);
        if (Constant.USER_IS_OPERATOR.equals(xtOperator.getIsOperator())) {
            return Response.error(-1, "非运营用户，不可以进行密码充值！");
        }
        // 需重置密码的用户
        User user = userMapper.selectByUserId(userId);
        if (null == user) {
            return Response.error(-2, "待重置密码用户不存在！");
        }
        String password = AuthUtils.md5Hex(Constant.USER_DEFAULT_PASSWORD, user.getSalt());
        user.setPassword(password);
        userMapper.updateById(user);
        return Response.ok();
    }

    /**
     * 绑定注册用户的手机号
     *
     * @param userId
     * @param mobile
     */
    @Override
    public void bindMobile(Integer userId, String mobile) {
        // 校验
        this.validWhenBindMobile(userId, mobile);
        // 保存手机号
        Customer customer1 = new Customer();
        customer1.setId(userId);
        customer1.setMobile(mobile);
        customerMapper.updateById(customer1);
    }

    /**
     * 微信退款
     *
     * @param recodPO
     * @param amount
     * @param batchId
     * @param user
     */
    @Transactional
    @Override
    public void wxRefundAmount(RechargeRecodPO recodPO, BigDecimal amount, String batchId, Integer changeType, User user) {

        this.validatedWhenWxRefundAmount(recodPO, amount);

        // 拼接请求参数
        WxPayRefundRequest request = this.buildWxPayRefundRequest(recodPO, amount, batchId);

        try {
            WxPayRefundResult result = wxPayService.refund(request);
            if (result.getReturnCode().equals("SUCCESS")) {
                // 卡退款
                if (Constant.RECHARGE_RECOD_DATA_TYPE_CARD.equals(recodPO.getDataType())) {
                    Card card = cardService.selectById(recodPO.getCardId());
                    cardService.updateAmountAndRecord(card.getCardNo(),
                            amount.negate(),
                            batchId,
                            changeType,
                            user
                    );
                }
                // 微信退款
                if (Constant.RECHARGE_RECOD_DATA_TYPE_ACCOUNT.equals(recodPO.getDataType())) {
                    // 申请退款成功,更新用户余额,记录一条日志
                    customerBalanceService.updateUserBalanceAndRecord(recodPO.getOpenId(),
                            amount.negate(),
                            batchId,
                            changeType,
                            user
                    );
                }
                logger.info("微信退款申请成功,入参:{},结果:{}", request, result);
            } else {
                logger.error("微信退款申请失败:入参:{},结果{}", request, result.getReturnMsg());
                throw new ServiceException("微信退款失败,请联系管理员");
            }
        } catch (WxPayException e) {
            logger.error("微信退款异常:{}", e);
            String msg = e.getErrCodeDes();
            msg = StringUtils.replace(msg, "refund_fee", "退款金额");
            throw new ServiceException(msg);
        }
    }

    private void validatedWhenWxRefundAmount(RechargeRecodPO recodPO, BigDecimal amount) {

        // 卡退款
        if (Constant.RECHARGE_RECOD_DATA_TYPE_CARD.equals(recodPO.getDataType())) {
            Card card = cardService.selectById(recodPO.getCardId());
            if (Objects.isNull(card)) {
                throw new ServiceException("卡不存");
            }
            if (amount.compareTo(card.getSum()) == 1) {
                if (Objects.isNull(card)) {
                    throw new ServiceException("卡余额不足");
                }
            }
        }

        // 账户退款
        CustomerBalance balance = customerBalanceService.selectByOpenId(recodPO.getOpenId());
        if (Constant.RECHARGE_RECOD_DATA_TYPE_ACCOUNT.equals(recodPO.getDataType())) {
            if (Objects.isNull(balance) || Objects.isNull(amount) || Objects.isNull(recodPO)) {
                throw new ServiceException("用户账户不存在,退款金额不能为空,充值记录不能为空!");
            }

            if (amount.compareTo(balance.getAmount()) == 1) {
                throw new ServiceException("账户余额不足!");
            }
        }

    }

    @Transactional
    @Override
    public void refundResult(String xmlData) {
        try {
            WxPayRefundNotifyResult result = wxPayService.parseRefundNotifyResult(xmlData);

            logger.info("微信退款回调:{}", result);

            if (result.getReturnCode().equals("SUCCESS")) {
                return;
            }
            // 处理失败时,根据核销记录,将用户的金额返回
            WxPayRefundNotifyResult.ReqInfo reqInfo = result.getReqInfo();

            // 退订批次号
            String refundId = reqInfo.getRefundId();

            HashMap<String, Object> param = Maps.newHashMap();
            param.put("recharge_number", refundId);

            List<RechargeRecodPO> records = rechargeRecodMapper.selectByMap(param);
            RechargeRecodPO recodPO = records.get(0);
            BigDecimal negate = recodPO.getQuantity().negate();

            recodPO.setType(Constant.RECHARGE_RECOD_TYPE_REFUND_ERROR);
            recodPO.setQuantity(negate);

            rechargeRecodMapper.insert(recodPO);
            customerBalanceMapper.updateAmountByOpenId(recodPO.getOpenId(), negate);

        } catch (WxPayException e) {
            logger.error("微信退款回调异常:{}", e);
        }
    }

    @Override
    @Transactional
    public void giveRefundAmount(RechargeRecodPO recodPO, BigDecimal refundAmount, String batchId, Integer changeType, User user) {
        // 校验入参
        validatedWhenWxRefundAmount(recodPO, refundAmount);

        // 更新卡余额
        if (Constant.RECHARGE_RECOD_DATA_TYPE_CARD.equals(recodPO.getDataType())) {
            Card card = cardService.selectById(recodPO.getCardId());
            cardService.updateAmountAndRecord(card.getCardNo(),
                    refundAmount.negate(),
                    batchId,
                    changeType,
                    user
            );
        }

        //更新账户余额
        if (Constant.RECHARGE_RECOD_DATA_TYPE_ACCOUNT.equals(recodPO.getDataType())) {
            // 申请退款成功,更新用户余额,记录一条日志
            customerBalanceService.updateUserBalanceAndRecord(recodPO.getOpenId(),
                    refundAmount.negate(),
                    batchId,
                    changeType,
                    user
            );
        }
    }

    /**
     * 拼接退款入参
     *
     * @return
     */
    private WxPayRefundRequest buildWxPayRefundRequest(RechargeRecodPO recodPO, BigDecimal amount, String batchId) {

        WxPayRefundRequest request = WxPayRefundRequest.newBuilder()
                .outTradeNo(recodPO.getRechargeNumber())
                .outRefundNo(batchId)
                .totalFee(recodPO.getQuantity().multiply(BigDecimal.valueOf(100)).intValue())
                .refundFee(amount.multiply(BigDecimal.valueOf(100)).intValue())
                .opUserId(mchId)
                .notifyUrl(notifyUrl)
                .build();

        return request;
    }

    private void validWhenBindMobile(Integer userId, String mobile) {
        if (Objects.isNull(userId) || StringUtils.isEmpty(mobile)) {
            throw new ServiceException("用户id或手机号不能为空");
        }
        if (!StringUtils.isPhoneNumber(mobile)) {
            throw new ServiceException("手机号格式不正确");
        }

        Map<String, Object> param = Maps.newHashMap();
        param.put("MOBILE", mobile);
        List<Customer> customerList = customerMapper.selectByMap(param);
        Customer customer = customerMapper.selectById(userId);

        if (Objects.isNull(customer)) {
            throw new ServiceException("用户不存在");
        }
        if (StringUtils.isNotEmpty(customer.getMobile())) {
            throw new ServiceException("该用户已经绑定手机号");
        }
        if (CollectionUtils.isNotEmpty(customerList)) {
            throw new ServiceException("手机号已被占用");
        }
    }
}
